WICONF.initCusLayer = {
    win: window
};
/**
 * @widoc $.initCusLayer
 * @namespace comp
 * @des 初始化弹出框
 * <span class="t_red">ps:一般情况推荐使用 $.initWiLayer，该接口封装了更常用的方法</span>
 * 组件配置，在使用组件前调用：
 <pre class="des-conf"> $.setWiConf('initCusLayer',{
    win:window// 默认生成弹框的窗口
 });</pre>
 * @type function
 * @param {function} callback 弹框中的页面可调用的回调函数（不再关闭弹框，关闭需调用 parent.closeLayer['..']()）
 *  - callback(args)
 *    args: {object|undefined} 弹框页面传回主页面的值
 * @param {string} apiName 当前组件对应的选中事件方法名，供弹出的 iframe 页面中调用，避免多个 layer 组件冲突
 * 开放 window.cusLayer 接口供 iframe 调用
 *  - window.cusLayer[apiName](args,w)
 *    args: {object|undefined} 弹框页面传回主页面的值
 *    w: 是否用弹框中的值覆盖原始值，仅当其为 true 时，会调用 callback(args)
 * - window.closeLayer[apiName]() 关闭当前弹窗
 * @param {object=} win 弹框时参照的 window对象，默认为当前 window。
 *    注：win指向的页面依赖外部组件1.2.3 layer，且以同一个win为弹框参照的cusLayer的apiName不得相同
 * @return {object|undefined} obj 返回对象
 * @rtn {function} obj.show(opts) 显示弹框
 *  - opts.content {string} 必须项，弹框页面 url
 *  - opts.title {string=} 弹框标题，默认不显示标题
 *  - opts.area {Array=} 弹框大小，默认为：['400px', '90%']
 */
$.initCusLayer = function(callback, apiName, win){
    if(!win) win = window;
    if(!win.layer) return;
    var curLayerIdx;// 记录当前弹窗索引，用于关闭
    if(!win.cusLayer) win.cusLayer = {};
    if(!win.closeLayer) win.closeLayer = {};
    win.cusLayer[apiName] = function(arg){
        callback && callback(arg);
    };
    win.closeLayer[apiName] = function(){
        win.layer.close(curLayerIdx);
    };
    return {
        show: function(showOpts){
            curLayerIdx = win.layer.open($.extend({// 扩展 layer.open 属性
                type: 2,
                title: false,
                //shadeClose: true,// 允许点遮罩层关闭
                shade: 0.5,// 遮罩层透明度
                area: ['400px', '90%'],
                cancel: win.closeLayer[apiName]
            }, showOpts));
            return curLayerIdx;
        }
    };
};
/**
 * @widoc $.initWiLayer
 * @namespace comp
 * @des 初始化弹出框
 * 注意：弹出页面中若需在弹框后执行操作，则应定义 window.initPage=function(name,data)
 * <span class="t_red">ps:一般情况推荐使用 $.initWiLayer，该接口封装了更常用的方法</span>
 * 组件配置，在使用组件前调用：
 <pre class="des-conf"> $.setWiConf('initCusLayer',{
    win:window// 默认生成弹框的窗口
 });</pre>
 * 弹出页必须定义 window.initPage 方法，弹出后将由组件自动调用，示例：
 <pre class="des-conf"> window.initPage = function(name, data, win){
    // win {object} 发起弹框的 window 对象（不一定是 window.parent，可能由子页面在 window.top 弹出）
    // name {string} win 中初始化弹框时传入的 opts.name
    // data {object} win 中传递的用户自定义参数
    // -------------
    // 关闭弹框：win.closeLayer[name]();
    // 调用 win 的回调：win.cusLayer[name](args); 其中 args 可以弹框页面的回调方法 callback 中获取
 };</pre>
 * @demo initWiLayer/demo 弹出框中显示页面
 * @type function
 * @param {object} opts 设置参数
 * @param {string} opts.name 弹出框的名称，必须保证当前页面中所有弹框名称的唯一性
 * @param {object} opts.layerOpts layer 的配置属性
 * @param {function=} opts.callback 开放给弹框页面的回调方法
 *  - function(args) 在子页面中通过 win.cusLayer[name](args) 触发
 * @return {object} obj 返回对象
 * @rtn {function} obj.show(showOpts) 显示弹框;
 *  - showOpts {object=} 与初始化参数 opts 类似，用于在初始化配置基础上进行修改
 *  -  showOpts.data {object=} 传递到弹框页面的参数，将在弹框页中 window.initPage(layerNmae,data,fromWin)
 *  -  showOpts.layerOpts {object=}
 *  -  showOpts.callback {function=}
 */
$.initWiLayer = function(opts){
    opts = $.extend({
        name: '',
        win: WICONF.initCusLayer.win,// 实际弹框的窗口
        //layerOpts:{content,title,area}
        callback: $.noop
    }, opts);
    var api;
    var win,// 实际弹框的窗口
        fromWin;// 触发弹框的窗口，不一定是弹窗的父窗口
    var oLayerOpts,// 初始化时传入的 layer 配置
        sApiName,// 弹框标识
        curLayerIdx;// 记录当前弹窗索引，用于关闭
    var fLayerCb;// fromeWin 开放给弹框的回调方法
    // 成功显示弹框后的回调
    var fSuccessHandler = function(userSuccess, data){
        return function(layero, index){
            var layerWin = win.frames['layui-layer-iframe' + index].window;
            layerWin.initPage && layerWin.initPage(sApiName, $.extend(undefined, data), fromWin);// 弹出子窗口后，初始化子窗口页面
            userSuccess && userSuccess(layero, index);
        };
    };
    // 弹框关闭时的回调
    var fCancelHandler = function(userCancel){
        return function(index, layero){
            userCancel && userCancel(index, layero);
            fromWin.closeLayer[sApiName]();
        }
    };
    // 显示弹框
    var fShow = function(showOpts){
        var fSuccessCb,fCancelCb,// 用户自定义的 success, cancel（opts.layerOpts 或 showOpts.layerOpts 中）
            layerOpts;
        if(!showOpts){
            showOpts = {};// 避免之后的处理报错
        }
        layerOpts = showOpts.layerOpts || {};// 同上
        fLayerCb = showOpts.callback || opts.callback;// fromeWin 开放给弹框的回调方法
        fSuccessCb = layerOpts.success || oLayerOpts.success;
        fCancelCb = layerOpts.cancel || oLayerOpts.cancel;
        delete layerOpts.success;// 将通过 fSuccessHandler() 封装，此处可从 layerOpts 中移除
        delete layerOpts.cancel;
        /* 弹框 */
        curLayerIdx = win.layer.open(
            $.extend({
                    type: 2,
                    title: false,
                    //area: ['400px', '90%'],
                    //shadeClose: true,// 允许点遮罩层关闭
                    shade: 0.5// 遮罩层透明度
                },
                oLayerOpts,// 初始化时的弹框配置
                layerOpts,// show 时传入的弹框配置
                {
                    content: showOpts.content,// TODO content 仅为支持旧版本，可等价于 showOpts.layerOpts.content
                    success: fSuccessHandler(fSuccessCb, showOpts.data),// 显示弹框后的回调，参数为：用户自定义的 layerOpts.success；弹框时传入的交互数据
                    cancel: fCancelHandler(fCancelCb)
                })
        );
        return curLayerIdx;
    };
    var fPreInit = function(){
        if(!fromWin.cusLayer){//不存在 fromWin.cusLayer,则创建此对象
            fromWin.cusLayer = {};
        }
        if(!fromWin.closeLayer){//不存在 fromWin.closeLayer,则创建此对象
            fromWin.closeLayer = {};
        }
    };
    var fInit = function(){
        win = opts.win;// 实际弹框的窗口
        fromWin = window;// 触发弹框的窗口，不一定是弹窗的父窗口
        if(!win.layer){// 未定义 layer 配置，或不支持 layer，将不执行有意义的操作
            api.show = $.noop;
            return;
        }
        fPreInit();
        /* 预处理完成，执行真正的初始化 */
        sApiName = opts.name;// 弹框标识
        oLayerOpts = opts.layerOpts;// 弹框配置
        fromWin.cusLayer[sApiName] = function(data){
            return fLayerCb(data);// 由于 show 时可能改变 fLayerCb 的引用，因此不能直接 fromWin.cusLayer[sApiName] = fLayerCb;
        };
        fromWin.closeLayer[sApiName] = function(){
            win.layer.close(curLayerIdx);// curLayerIdx 将在 show 之后才能确定
        };
    };
    api = {
        show: fShow
    };
    fInit();
    return api;
};